package org.future.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

public class MiniServer {
	private int port = ConfigUtil.getInt("srv_port");
	private int backlog = 42;
	private ServerSocket server_socket;
	private ExecutorService threadPool;
	private final int POOL_SIZE = 7;
	private boolean isShutDown = false;
	private int shutdown_port = ConfigUtil.getInt("srv_shut_port");
	private ServerSocket shutdown_srv_socket;
	
	public MiniServer()throws IOException{
		server_socket = new ServerSocket();
		server_socket.setReuseAddress(true);
		server_socket.bind(new InetSocketAddress(port),backlog);
		int system_cpu_total = Runtime.getRuntime().availableProcessors();
		threadPool = Executors.newFixedThreadPool(POOL_SIZE * system_cpu_total);
		// listening shutdown command
		shutdown_srv_socket = new ServerSocket(shutdown_port);
		getShutDownThread().start();
		System.out.println("--- server started! ---");
	}
	
	public void service(){
		while(!isShutDown){
			Socket socket = null;
			try{
				socket = server_socket.accept();
				threadPool.execute(new WorkHandler(socket));
			} catch(SocketTimeoutException e){
				// ignore the timeout has been reached
			} catch(RejectedExecutionException rEe){
				// threadPool isShutdown and can not accept the task
				try{
					if(socket != null){
						socket.close();
					}
				} catch(Exception e){
				}
			} catch(SocketException skExp){
				// server_socket isClosed
			} catch(Exception exp){
				exp.printStackTrace();
				try{
					if(socket != null){
						socket.close();
					}
				} catch(Exception e){
				}
			}
		}// end while
	}
	
	private Thread getShutDownThread(){
		Thread shut = new Thread(){
			public void start() {
			    setDaemon(true);
			    super.start();
			}
			public void run() {
			    while(!isShutDown){
			    	Socket socket = null;
			    	try{
			    		socket = shutdown_srv_socket.accept();
			    		// get in and out
			    		BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			    		PrintWriter out = new PrintWriter(socket.getOutputStream());
			    		// listening come in command
			    		String command = null;
			    		while((command = in.readLine()) != null){
							if(command.equalsIgnoreCase("shutdown")){
								break;
							}
						}
			    		// start shutdown
			    		long beginTime = System.currentTimeMillis();
			    		out.println("The server will be shutdown...");
			    		out.flush();
			    		isShutDown = true;
			    		// 请求关闭线程池,不再接收任务
			    		threadPool.shutdown();
			    		// 等待关闭线程池
			    		while(!threadPool.isTerminated()){
			    			threadPool.awaitTermination(10, TimeUnit.SECONDS);
			    		}
			    		// 关闭服务端
			    		server_socket.close();
			    		long endTime = System.currentTimeMillis();
			    		out.println("The Server has shutdown.");
			    		out.println("elapsed time:" + (endTime - beginTime) + "ms");
			    		out.flush();
			    		socket.close();
			    		shutdown_srv_socket.close();
			    	} catch(Exception e){
			    		e.printStackTrace();
			    	}
			    }// end while
			}
		};
		return shut;
	}
	
	public static void main(String[] args)throws Exception {
		MiniServer server = new MiniServer();
	    server.service();
    }
}
